package cn.xorange.commons.utils.lang;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author : yangjian
 * @date : 2023/11/22
 * @description :
 */
public class ObjectUtils {


    public static Boolean isEmpty(Object val){
        if(Objects.isNull(val)){
            return true;
        }
        if(val instanceof String){
            return val.toString().isEmpty();
        }
        if(val instanceof Collection){
            return ((Collection<?>) val).isEmpty();
        }
        if(val.getClass().isArray()){
            return false;
        }
        if(val instanceof Map){
            return ((Map<?, ?>) val).isEmpty();
        }
        return val.toString().isEmpty();
    }

    /**
     * 将对象转为字符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj 对象
     * @param charset 字符集
     * @return 字符串
     */
    public static String str(Object obj, Charset charset) {
        if (null == obj)
        {
            return null;
        }

        if (obj instanceof String)
        {
            return (String) obj;
        }
        else if (obj instanceof byte[])
        {
            return str((byte[]) obj, charset);
        }
        else if (obj instanceof Byte[])
        {
            byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
            return str(bytes, charset);
        }
        else if (obj instanceof ByteBuffer)
        {
            return str((ByteBuffer) obj, charset);
        }
        return obj.toString();
    }


    /**
     * 将对象转为字符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj 对象
     * @return 字符串
     */
    public static String utf8Str(Object obj) {
        return str(obj, StandardCharsets.UTF_8);
    }


    public static String toString(Object obj){
        if(Objects.isNull(obj)){
            return "";
        }else {
            return String.valueOf(obj);
        }
    }

    public static int toInt(Object obj){
        return cn.hutool.core.convert.Convert.toInt(obj,0);
    }

    public static Long toLong(final Object val) {
        if(Objects.isNull(val)){
            return 0L;
        }else {
            return Long.parseLong(val.toString());
        }
    }

    public static Float toFloat(final Object val) {
        if(Objects.isNull(val)){
            return (float) 0.0;
        }else {
            return Float.parseFloat(val.toString());
        }
    }

    public static Double toDouble(final Object val) {
        if (val == null) {
            return 0D;
        }
        try {
            return toDouble(CharSequenceUtil.trim(val.toString()));
        } catch (Exception e) {
            return 0D;
        }
    }

    /**
     * 转换为Boolean类型 'true', 'on', 'y', 't', 'yes' or '0' (case insensitive) will return true. Otherwise, false is returned.
     */
    public static Boolean toBoolean(final Object val) {
        if (val == null) {
            return false;
        }
        return BooleanUtil.toBoolean(val.toString()) || "0".equals(val.toString());
    }

    public static Date toDate(final Object val){
        if (Objects.nonNull(val) && val instanceof String){
            try {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(val.toString());
            }catch (Exception e){
                try {
                    return new SimpleDateFormat("yyyy-MM-dd").parse(val.toString());
                }catch (Exception e1){
                    try {
                        return new SimpleDateFormat("HH:mm:ss").parse(val.toString());
                    }catch (Exception e2){
                        return null;
                    }
                }
            }
        }
        return toDate(val);
    }

    public static byte toByte(final Object val){
        return cn.hutool.core.convert.Convert.toByte(val);
    }
    public static Short toShort(final Object val){
        return cn.hutool.core.convert.Convert.toShort(val);
    }
    public static <T> List<T> toList(Object object, Class<T> clazz){
        return Convert.toList(clazz,object);
    }
    public static List<Object> toList(Object objVal){
        // 格式化val
        List<Object> lst = new ArrayList<>();
        if(objVal instanceof Collection){
            for(Object obj : (Collection)objVal){
                lst.add(obj);
            }
        } else  if (objVal instanceof String && ((String) objVal).startsWith("[")){
            JSONArray array = JSON.parseArray(objVal.toString());
            lst.addAll(array);
        }
        else if(objVal.getClass().isArray()){
            int length = Array.getLength(objVal);
            for(int i = 0; i<length;i++ ){
                lst.add(Array.get(objVal,i));
            }
        }else {
            Object[] oj = objVal.toString().split(",");
            Collections.addAll(lst,oj);
        }
        return lst;
    }


    public static Boolean isNumber(Object obj){
        return cn.hutool.core.util.NumberUtil.isNumber(obj.toString());
    }
    public static Boolean isMap(Object obj){
        return Objects.nonNull(obj) && obj instanceof Map;
    }
    public static Boolean isCollection(Object obj){
        return Objects.nonNull(obj) && obj instanceof Collection;
    }
    public static Boolean isArray(Object obj){
        return Objects.nonNull(obj) && obj.getClass().isArray();
    }
    /**
     * 比较大小
     * @param obj1
     * @param obj2
     * @return
     */
    public static boolean compareLarge(Object obj1, Object obj2){
        if (Objects.isNull(obj1) && Objects.nonNull(obj2)){
            return false;
        }else if(Objects.nonNull(obj1) && Objects.isNull(obj2)){
            return true;
        }else if(obj1 instanceof Date || obj2 instanceof Date){
            return ((Date)obj1).compareTo((Date)obj2)>0;
        }else if(obj1 instanceof Integer || obj2 instanceof Integer){
            return ObjectUtils.toInt(obj1)> ObjectUtils.toInt(obj2);
        } else if(obj1 instanceof Float || obj2 instanceof Float){
            return ObjectUtils.toFloat(obj1)> ObjectUtils.toFloat(obj2);
        }else if(obj1 instanceof Double || obj2 instanceof Double){
            return ObjectUtils.toDouble(obj1)> ObjectUtils.toDouble(obj2);
        }else {
            return ObjectUtil.toString(obj1).compareTo(ObjectUtil.toString(obj2))>0;
        }
    }

}
